<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
    <meta name="description" content="Interested in adding textures, lighting, shadows, normal maps, glowing objects, ambient occlusion, reflections, refractions, and more to your 3D game? Great! 3D Game Shaders For Beginners is a collection of shading techniques that will take your game visuals to new heights." />
    <meta property="og:title" content="Depth Of Field | 3D Game Shaders For Beginners" />
    <meta property="og:description" content="Interested in adding textures, lighting, shadows, normal maps, glowing objects, ambient occlusion, reflections, refractions, and more to your 3D game? Great! 3D Game Shaders For Beginners is a collection of shading techniques that will take your game visuals to new heights." />
    <meta property="og:image" content="https://i.imgur.com/JIDwVTm.png" />
    <meta name="twitter:title" content="Depth Of Field | 3D Game Shaders For Beginners" />
    <meta name="twitter:description" content="Interested in adding textures, lighting, shadows, normal maps, glowing objects, ambient occlusion, reflections, refractions, and more to your 3D game? Great! 3D Game Shaders For Beginners is a collection of shading techniques that will take your game visuals to new heights." />
    <meta name="twitter:image" content="https://i.imgur.com/JIDwVTm.png" />
    <meta name="twitter:card" content="summary_large_image" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
    <meta name="author" content="David Lettier" />
    <title>Depth Of Field | 3D Game Shaders For Beginners</title>
    <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
    </style>
    <style>
      code.sourceCode > span { display: inline-block; line-height: 1.25; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode { white-space: pre; position: relative; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      code.sourceCode { white-space: pre-wrap; }
      code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          background-color: #232629;
          color: #7a7c7d;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #7a7c7d;  padding-left: 4px; }
      div.sourceCode
        { color: #cfcfc2; background-color: #232629; }
      @media screen {
      code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span. { color: #cfcfc2; } /* Normal */
      code span.al { color: #95da4c; } /* Alert */
      code span.an { color: #3f8058; } /* Annotation */
      code span.at { color: #2980b9; } /* Attribute */
      code span.bn { color: #f67400; } /* BaseN */
      code span.bu { color: #7f8c8d; } /* BuiltIn */
      code span.cf { color: #fdbc4b; } /* ControlFlow */
      code span.ch { color: #3daee9; } /* Char */
      code span.cn { color: #27aeae; } /* Constant */
      code span.co { color: #7a7c7d; } /* Comment */
      code span.cv { color: #7f8c8d; } /* CommentVar */
      code span.do { color: #a43340; } /* Documentation */
      code span.dt { color: #2980b9; } /* DataType */
      code span.dv { color: #f67400; } /* DecVal */
      code span.er { color: #da4453; } /* Error */
      code span.ex { color: #0099ff; } /* Extension */
      code span.fl { color: #f67400; } /* Float */
      code span.fu { color: #8e44ad; } /* Function */
      code span.im { color: #27ae60; } /* Import */
      code span.in { color: #c45b00; } /* Information */
      code span.kw { color: #cfcfc2; } /* Keyword */
      code span.op { color: #cfcfc2; } /* Operator */
      code span.ot { color: #27ae60; } /* Other */
      code span.pp { color: #27ae60; } /* Preprocessor */
      code span.re { color: #2980b9; } /* RegionMarker */
      code span.sc { color: #3daee9; } /* SpecialChar */
      code span.ss { color: #da4453; } /* SpecialString */
      code span.st { color: #f44f4f; } /* String */
      code span.va { color: #27aeae; } /* Variable */
      code span.vs { color: #da4453; } /* VerbatimString */
      code span.wa { color: #da4453; } /* Warning */
    </style>
    <!--[if lt IE 9]>
      <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
<p><a href="outlining.html"><span class="emoji" data-emoji="arrow_backward">◀️</span></a> <a href="index.html"><span class="emoji" data-emoji="arrow_double_up">⏫</span></a> <a href="#"><span class="emoji" data-emoji="arrow_up_small">🔼</span></a> <a href="#copyright"><span class="emoji" data-emoji="arrow_down_small">🔽</span></a> <a href="posterization.html"><span class="emoji" data-emoji="arrow_forward">▶️</span></a></p>
<h1 id="3d-game-shaders-for-beginners">3D Game Shaders For Beginners</h1>
<h2 id="depth-of-field">Depth Of Field</h2>
<p align="center">
<img src="https://i.imgur.com/DEa77Bh.gif" alt="Depth Of Field" title="Depth Of Field">
</p>

<p>Like <a href="ssao.html">SSAO</a>, depth of field is an effect you can't live without once you've used it. Artistically, you can use it to draw your viewer's eye to a certain subject. But in general, depth of field adds a lot of realism for a little bit of effort.</p>
<h3 id="in-focus">In Focus</h3>
<p>The first step is to render your scene completely in focus. Be sure to render this into a framebuffer texture. This will be one of the inputs to the depth of field shader.</p>
<h3 id="out-of-focus">Out Of Focus</h3>
<p>The second step is to blur the scene as if it was completely out of focus. Like bloom and SSAO, you can use a <a href="blur.html#box-blur">box blur</a>. Be sure to render this out-of-focus-scene into a framebuffer texture. This will be one of the inputs to the depth of field shader.</p>
<h4 id="bokeh">Bokeh</h4>
<p align="center">
<img src="https://i.imgur.com/aQ9Ga8J.gif" alt="Bokeh" title="Bokeh">
</p>

<p>For a great bokeh effect, dilate the out of focus texture and use that as the out of focus input. See <a href="dilation.html">dilation</a> for more details.</p>
<h3 id="mixing">Mixing</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1"></a>  <span class="co">// ...</span></span>
<span id="cb1-2"><a href="#cb1-2"></a></span>
<span id="cb1-3"><a href="#cb1-3"></a>  <span class="dt">float</span> minDistance = <span class="fl">1.0</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a>  <span class="dt">float</span> maxDistance = <span class="fl">3.0</span>;</span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a>  <span class="co">// ...</span></span></code></pre></div>
<p>Feel free to tweak these two parameters. All positions at or below <code>minDistance</code> will be completely in focus. All positions at or beyond <code>maxDistance</code> will be completely out of focus.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="#cb2-1"></a>  <span class="co">// ...</span></span>
<span id="cb2-2"><a href="#cb2-2"></a></span>
<span id="cb2-3"><a href="#cb2-3"></a>  vec4 focusColor      = texture(focusTexture, texCoord);</span>
<span id="cb2-4"><a href="#cb2-4"></a>  vec4 outOfFocusColor = texture(outOfFocusTexture, texCoord);</span>
<span id="cb2-5"><a href="#cb2-5"></a></span>
<span id="cb2-6"><a href="#cb2-6"></a>  <span class="co">// ...</span></span></code></pre></div>
<p>You'll need the in focus and out of focus colors.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1"></a>  <span class="co">// ...</span></span>
<span id="cb3-2"><a href="#cb3-2"></a></span>
<span id="cb3-3"><a href="#cb3-3"></a>  vec4 position = texture(positionTexture, texCoord);</span>
<span id="cb3-4"><a href="#cb3-4"></a></span>
<span id="cb3-5"><a href="#cb3-5"></a>  <span class="co">// ...</span></span></code></pre></div>
<p>You'll also need the vertex position in view space. You can reuse the position framebuffer texture you used for <a href="ssao.html#vertex-positions">SSAO</a>.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb4-1"><a href="#cb4-1"></a>  <span class="co">// ...</span></span>
<span id="cb4-2"><a href="#cb4-2"></a></span>
<span id="cb4-3"><a href="#cb4-3"></a>  vec4 focusPoint = texture(positionTexture, mouseFocusPoint);</span>
<span id="cb4-4"><a href="#cb4-4"></a></span>
<span id="cb4-5"><a href="#cb4-5"></a>  <span class="co">// ...</span></span></code></pre></div>
<p>The focus point is a position somewhere in your scene. All of the points in your scene are measured from the focus point.</p>
<p>Choosing the focus point is up to you. The demo uses the scene position directly under the mouse when clicking the middle mouse button. However, it could be a constant distance from the camera or a static position.</p>
<p align="center">
<img src="https://i.imgur.com/idDZr62.png" alt="smoothstep" title="smoothstep">
</p>

<div class="sourceCode" id="cb5"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb5-1"><a href="#cb5-1"></a>  <span class="co">// ...</span></span>
<span id="cb5-2"><a href="#cb5-2"></a></span>
<span id="cb5-3"><a href="#cb5-3"></a>  <span class="dt">float</span> blur =</span>
<span id="cb5-4"><a href="#cb5-4"></a>    smoothstep</span>
<span id="cb5-5"><a href="#cb5-5"></a>      ( minDistance</span>
<span id="cb5-6"><a href="#cb5-6"></a>      , maxDistance</span>
<span id="cb5-7"><a href="#cb5-7"></a>      , abs(position.y - focusPoint.y)</span>
<span id="cb5-8"><a href="#cb5-8"></a>      );</span>
<span id="cb5-9"><a href="#cb5-9"></a></span>
<span id="cb5-10"><a href="#cb5-10"></a>  <span class="co">// ...</span></span></code></pre></div>
<p><code>smoothstep</code> returns values from zero to one. The <code>minDistance</code> is the left-most edge. Any position less than the minimum distance, from the focus point, will be in focus or have a blur of zero. The <code>maxDistance</code> is the right-most edge. Any position greater than the maximum distance, from the focus point, will be out of focus or have a blur or one. For distances between the edges, blur will be between zero and one. These values are interpolated along a s-shaped curve.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb6-1"><a href="#cb6-1"></a></span>
<span id="cb6-2"><a href="#cb6-2"></a>  <span class="co">// ...</span></span>
<span id="cb6-3"><a href="#cb6-3"></a></span>
<span id="cb6-4"><a href="#cb6-4"></a>  fragColor = mix(focusColor, outOfFocusColor, blur);</span>
<span id="cb6-5"><a href="#cb6-5"></a></span>
<span id="cb6-6"><a href="#cb6-6"></a>  <span class="co">// ...</span></span></code></pre></div>
<p>The <code>fragColor</code> is a mixture of the in focus and out of focus color. The closer <code>blur</code> is to one, the more it will use the <code>outOfFocusColor</code>. Zero <code>blur</code> means this fragment is entirely in focus. At <code>blur &gt;= 1</code>, this fragment is completely out of focus.</p>
<h3 id="source">Source</h3>
<ul>
<li><a href="https://github.com/lettier/3d-game-shaders-for-beginners/blob/master/demonstration/src/main.cxx" target="_blank" rel="noopener noreferrer">main.cxx</a></li>
<li><a href="https://github.com/lettier/3d-game-shaders-for-beginners/blob/master/demonstration/shaders/vertex/basic.vert" target="_blank" rel="noopener noreferrer">basic.vert</a></li>
<li><a href="https://github.com/lettier/3d-game-shaders-for-beginners/blob/master/demonstration/shaders/fragment/box-blur.frag" target="_blank" rel="noopener noreferrer">box-blur.frag</a></li>
<li><a href="https://github.com/lettier/3d-game-shaders-for-beginners/blob/master/demonstration/shaders/fragment/depth-of-field.frag" target="_blank" rel="noopener noreferrer">depth-of-field.frag</a></li>
</ul>
<h2 id="copyright">Copyright</h2>
<p>(C) 2019 David Lettier <br> <a href="https://www.lettier.com">lettier.com</a></p>
<p><a href="outlining.html"><span class="emoji" data-emoji="arrow_backward">◀️</span></a> <a href="index.html"><span class="emoji" data-emoji="arrow_double_up">⏫</span></a> <a href="#"><span class="emoji" data-emoji="arrow_up_small">🔼</span></a> <a href="#copyright"><span class="emoji" data-emoji="arrow_down_small">🔽</span></a> <a href="posterization.html"><span class="emoji" data-emoji="arrow_forward">▶️</span></a></p>
  </body>
</html>
